package com.web.kdl.util;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author： shulibin
 * @Date： 2025/7/28 8:55
 * @Describe：
 */

@Component
public class RedisUtils {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private ObjectMapper objectMapper;

    private static final Long RELEASE_SUCCESS = 1L;
    private static final String RELEASE_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
            "return redis.call('del', KEYS[1]) " +
            "else " +
            "return 0 " +
            "end";;


    // 设置键值对
    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    // 设置键值对并指定过期时间
    public void set(String key, Object value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }

    // 设置键值对并指定过期时间
    public void set(String key, Object value, long seconds) {
        redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);
    }

    // 获取值
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    // 获取值
    public String getString(String key) {
        Object obj = redisTemplate.opsForValue().get(key);
        return obj == null ? null : obj.toString();
    }
    
    // 获取布尔值
    public Boolean getBoolean(String key) {
        Object obj = redisTemplate.opsForValue().get(key);
        if (obj == null) {
            return null;
        }
        if (obj instanceof Boolean) {
            return (Boolean) obj;
        }
        if (obj instanceof String) {
            return Boolean.parseBoolean((String) obj);
        }
        if (obj instanceof Number) {
            return ((Number) obj).intValue() != 0;
        }
        return false;
    }
    
    // 递增
    public Long increment(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    // 删除键
    public Boolean delete(String key) {
        return redisTemplate.delete(key);
    }

    // 判断键是否存在
    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    // 如果不存在，则设置
    public Boolean setNx(String key, Object value) {
        return redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    // 如果不存在，则设置，附带过期时间
    public Boolean tryLock(String lockKey, String requestId, long seconds) {
        return redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, seconds, TimeUnit.SECONDS);
    }

    // 如果不存在，则设置，附带过期时间
    public Boolean tryLock(String lockKey, String requestId, long timeout, TimeUnit unit) {
        return redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, timeout, unit);
    }

    // 不存在返回true，存在则删除
    public Boolean releaseLock(String lockKey, String requestId){
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(RELEASE_SCRIPT);
        redisScript.setResultType(Long.class);
        Long result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), Collections.singletonList(requestId));
        return RELEASE_SUCCESS.equals(result);
    }
    /**
     * 从右侧添加单个元素，如果 key 不存在自动创建 List
     */
    public <T> void rightPush(String key, T value) {
        try {
            String json = objectMapper.writeValueAsString(value);
            redisTemplate.opsForList().rightPush(key, json);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("对象序列化失败", e);
        }
    }

    /**
     * 获取整个列表
     * @param key Redis key
     * @param clazz 元素类型
     * @param <T> 泛型
     * @return List<T>，如果 key 不存在返回空 List
     */
    public <T> List<T> getAll(String key, Class<T> clazz) {
        List<?> jsonList = redisTemplate.opsForList().range(key, 0, -1);
        List<T> result = new ArrayList<>();
        if (jsonList != null) {
            for (Object obj : jsonList) {
                try {
                    if (obj != null) {
                        result.add(objectMapper.readValue(obj.toString(), clazz));
                    }
                } catch (Exception e) {
                    throw new RuntimeException("对象反序列化失败", e);
                }
            }
        }
        return result;
    }
    public void saveMap(String key, String field, List<?> list) {
        Map<String, Object> map = new HashMap<>();
        map.put(field, JSON.toJSONString(list));
        redisTemplate.opsForHash().putAll(key, map);
    }

    /**
     * 获取 Redis Map 并把所有 value 合并成一个 List<T>
     * @param key Redis key
     * @param clazz List 元素类型 FlywheelDataAnalysis
     */
    public <T> List<T> getMap(String key, Class<T> clazz) {
        Map<Object, Object> map = redisTemplate.opsForHash().entries(key); // 获取整个 Map
        if (map == null || map.isEmpty()) return Collections.emptyList();

        List<T> result = new ArrayList<>();

        for (Object value : map.values()) {
            if (value == null) continue;

            // 因为存的时候统一是 JSON 字符串
            result.addAll(JSON.parseArray((String) value, clazz));
        }

        return result;
    }

}
